﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace Super_Pong.Classes
{
    public class Animation
    {
        #region Atributos
        private List<Frame> ImageList;
        private long totalDuration;
        private long animTime;
        private int currentFrameIndex;
        private bool paused;
        #endregion

        #region Construtores
        /// <summary>
        /// Construtor padrão.
        /// </summary>
        public Animation()
        {
            //Cria a lista
            ImageList = new List<Frame>();

            //Animation percent = 0
            currentFrameIndex = 0;

            //Start running
            paused = false;
        }

        /// <summary>
        /// Construtor extendido da animação.
        /// </summary>
        /// <param name="image">Uma array com todas as imagens dessa animação.</param>
        /// <param name="t">O tempo de duração padrão para essas imagens.</param>
        public Animation(Texture2D[] image, long t)
        {
            //Inicializa a lista
            ImageList = new List<Frame>();

            //Adiciona imagem por imagem com o tempo desejado
            for (int i = 0; i < image.Length; i++)
            {
                this.AddFrame(image[i],t);
            }

            //Animation percent = 0
            currentFrameIndex = 0;

            //Start running
            paused = false;
        }
        #endregion

        #region Metodos
        /// <summary>
        /// Adiciona uma frame a animação.
        /// </summary>
        /// <param name="tex">A imagem para colocar na frame.</param>
        /// <param name="time">O tempo de duração desse frame.</param>
        public void AddFrame(Texture2D tex, long time)
        {
            //Se o tempo for valido e a textura nao for nula adiciona na lista
            if (time > 0 && tex != null)
            {
                //Soma no tempo total para atualizar
                totalDuration += time;
                //Cria um frame para adicionar
                Frame f = new Frame(tex, totalDuration);
                //Adiciona
                ImageList.Add(f);
            }
        }

        /// <summary>
        /// Update the animation.
        /// </summary>
        /// <param name="gameTime">The game time.</param>
        public void Update(GameTime gameTime)
        {
            //Se nao esta pausado roda normalmente
            if (!paused)
            {
                //So gasta tempo calculando se existe mais que um frame
                if (ImageList.Count() > 1)
                {
                    //O tempo sendo menor que a duração é somado pelo delay do jogo
                    if (animTime < totalDuration)
                    {
                        animTime += gameTime.ElapsedGameTime.Milliseconds;
                    }

                    if (animTime >= totalDuration || currentFrameIndex > ImageList.Count)
                    {
                        //Tempo maior que a duração = reset
                        animTime = 0L;
                        currentFrameIndex = 0;
                    }

                    //Tempo atual da animação muda de frame
                    while (animTime > GetFrame(currentFrameIndex).endTime)
                    {
                        currentFrameIndex++;
                    }
                }
                else
                {
                    //Mostra o unico frame
                    if (currentFrameIndex != 0)
                        currentFrameIndex = 0;
                }
            }
        }

        /// <summary>
        /// Pega um frame da animação.
        /// </summary>
        /// <param name="index">O index do frame (null se estiver outofbounds).</param>
        /// <returns>[Texture2D] a frame cujo index foi passado.</returns>
        public Frame GetFrame(int index)
        {
            if (index < ImageList.Count)
                return ImageList[index];
            else
                return null;
        }

        /// <summary>
        /// Retorna a imagem da frame atual na animação.
        /// </summary>
        /// <returns>[Texture2D] a Imagem da frame atual da animação.</returns>
        public Texture2D GetCurrentImage()
        {
            //Proteção para um acesso outOfBounds
            if (GetFrame(currentFrameIndex) != null)
            {
                return GetFrame(currentFrameIndex).image;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// Seta o estado atual da animação.
        /// </summary>
        /// <param name="state">É passado a variavel paused que controla o estado da animação.</param>
        public void SetPaused(bool state){
            paused = state;
        }

        /// <summary>
        /// Reseta a animação para o começo.
        /// </summary>
        public void Reset()
        {
            currentFrameIndex = 0;
            animTime = 0L;
        }

        /// <summary>
        /// Pega a porcentagem de execução da animação.
        /// </summary>
        /// <returns>[float] a porcentagem (pelo tempo) que a animação ja passou.</returns>
        public float GetPercentage()
        {
            return ((float)animTime) / ((float)totalDuration);
        }
        #endregion

        #region InnerClasses
        public class Frame
        {
            public long endTime = 0;
            public Texture2D image;

            public Frame(Texture2D tex, long t)
            {
                image = tex;
                endTime = t;
            }
        }
        #endregion
    }
}
